"use strict"
import "./ramda.js"

export class Clock {
    static default_fps() {return 20}
    constructor() {
        this._gap_ms = 1000 / Clock.default_fps()
        this._frame_watchs = []
    }
    _on_frame(){
        if (this._gap_ms > 0){
            this._frame_watchs.forEach(R.applyTo(undefined))
            setTimeout(()=>{this._on_frame()}, this._gap_ms)
        }
    }
    frame_join(f){
        if (R.is(Function, f)){
            this._frame_watchs.push(f)
        }
        return this
    }
    start(fps=undefined){
        if (R.is(Number, fps)) {
            this._gap_ms = R.max(1000/fps, 1)
        }
        setTimeout(()=>{this._on_frame()}, 0)
        return this
    }
    stop(){
        this._gap_ms = 0
        return this
    }
    now_ms(){
        return Date.now()
    }
    now_second(){
        return Math.floor(Date.now() / 1000)
    }
    sync_refresh(f){
        function loop(){
            if ((this._gap_ms > 0) && (f() == undefined)){
                window.requestAnimationFrame(loop)
            }
        }
        this._gap_ms = 1
        return window.requestAnimationFrame(loop)
    }
}

import "./jquery.js"

export function $(selector) {
    return jQuery(selector)
}

function make_eventp(user, _init) {
    for (const f in user) {
        if (_init.hasOwnProperty(f)) {_init[f] = user[f]}
    }
    return _init
}
function event_fn_nil() {
    return (_=undefined)=>{}
}
const EVENT_FN_NIL = event_fn_nil()
function base_eventp(ext={}) {
    const eventp = {
        on_init: EVENT_FN_NIL,
        on_frame: EVENT_FN_NIL,
    }
    for (const f in ext) {
        eventp[f] = ext[f]
    }
    return eventp
}
function done_widget(eventp, widget) {
    eventp.on_init(widget)
    return ()=>{eventp.on_frame(widget)}
}

export function Label(dom, _eventp={}, init_text="") {
    const eventp = make_eventp(_eventp, base_eventp({
        on_click: EVENT_FN_NIL,
    }))
    const widget = {
        text(){return dom.html()},
        update(text){
            if (widget.text() != text) {
                dom.html(text)
            }
        },
    }
    dom.on("click", ()=>{eventp.on_click()})
    widget.update(init_text)
    return done_widget(eventp, widget)
}

export function Button(dom, _eventp={}) {
    const eventp = make_eventp(_eventp, base_eventp({
        on_click: EVENT_FN_NIL,
    }))
    const widget = {}
    dom.on("click", ()=>{eventp.on_click()})
    return done_widget(eventp, widget)
}
export function PushButton(dom, fn_click) {
    return Button(dom, {on_click:fn_click})
}

export function Select(dom, _eventp={}) {
    const eventp = make_eventp(_eventp, base_eventp({
        on_select: EVENT_FN_NIL,
    }))
    const obj = dom.get(0)
    const widget = {
        foreach(fn){
            for (const i in obj) {
                const dom_option = $(obj.options[i])
                const ux_value = dom_option.attr("ux-value")
                if (fn(i, dom_option, ux_value)) {break}
            }
        },
        select_with_eq(ux_value){
            widget.foreach((i, dom_option, opt_value)=>{
                if (opt_value == ux_value) {
                    obj.selectedIndex = i
                    return true
                }
            })
        },
    }
    dom.bind("change", ()=>{
        const i = obj.selectedIndex
        const dom_option = $(obj.options[i])
        const ux_value = dom_option.attr("ux-value")
        eventp.on_select(dom_option, ux_value, widget)
    })
    return done_widget(eventp, widget)
}

export function CheckBox(dom, _eventp={}) {
    const eventp = make_eventp(_eventp, base_eventp({
        on_change: EVENT_FN_NIL,
    }))
    const widget = {
        is_checked(){
            return Boolean(dom.prop("checked"))
        },
        checked(to_status){
            dom.prop("checked", to_status)
            return widget
        },
    }
    dom.on("click", ()=>{
        eventp.on_change(widget)
    })
    return done_widget(eventp, widget)
}

export function adaption_mobile_width(pc_body_width_rate){
    const dom_doc = $(document)
    const dom_body = $(document.body)
    if (dom_doc.width() * 1.3 > dom_doc.height()){
        const width = `${Math.round(dom_doc.height() * pc_body_width_rate)}px`
        dom_body.css("min-width", width).css("max-width", width)
        return "pc"
    }
    return this
}

export class FrameSystem {
    constructor() {
        this._frame_fns = []
        this._event_quene = []
    }

    frame_join(fn) {
        this._frame_fns.push(fn)
    }

    on_frame() {
        this._frame_fns.forEach(R.applyTo(this))
    }

    event_push(name, val) {
        this._event_quene.push([name,val])
    }

    event_poll(name) {
        const i = R.findIndex((a)=>(a[0] == name), this._event_quene)
        const _event_quene = this._event_quene
        return {
            on(fn){
                if (i >= 0) {
                    const val = _event_quene[i][1]
                    const fn_take = ()=>{
                        if (_event_quene.length > 1) {
                            _event_quene[i] = _event_quene.at(-1)
                        }
                        if (_event_quene.length > 0) {
                            _event_quene.pop()
                        }
                    }
                    fn(val, fn_take)
                }
            }
        }
    }
}

export default {
    adaption_mobile_width,
    Clock, FrameSystem,
    $, Label, Button, PushButton, Select, CheckBox,
}

